Skip to content

verify-baseline-static: allowlist the UCRT _powf_special switch table on Windows x64 - #45886

Open
robobun wants to merge 2 commits into
mainfrom
robobun/9dd25751/allowlist-powf-special
Open

robobun wants to merge 2 commits into
mainfrom
robobun/9dd25751/allowlist-powf-special

Conversation

@robobun

@robobun robobun commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Fix

  • Add _powf_special as a blanket pass to the data-in-.text group of allowlist-x64-windows.txt, beside the strspn family.
  • Correct because its 61 instructions need SSE2 at most. An [AVX] ceiling is not enough: most flagged layouts decode another feature.
  • Verified: the failing table bytes, spliced into build 127915's bun-profile.exe. The scan fails as in CI on main's allowlist and passes on this one.
  • Self-reviewed: 8 concerns raised, 7 addressed. Not done: a tracking issue for a scan that skips these tables.

Background

  • The step disassembles .text and fails on an instruction Nehalem cannot run, unless the allowlist names the symbol.
  • A table entry is the image-relative address of a case label, so it changes with link layout. About 0.06% of nearby positions flag it, and 74% in a band 10.5 MiB above.
  • Considered that scan: the PDB marks each table with an S_LDATA32 record. It is a separate change, and it deletes this group.

Downsides

  • The scan no longer reports a real post-baseline instruction inside _powf_special.
  • Covers only the four functions linked today (the pinned UCRT has 11 more). llint_entry [AVX] is not changed.
Notes

Builds with this violation. 19 builds print it, all at 0x014519c364, created from 2026-10-16T21:52Z to 2026-10-17T02:36Z:

Main before it (126975, 0b2d346) and after it (127065, 4334326) passes the step. A retry does not help: the result is fixed for a given binary.

Why so many builds share one layout. The linker map has one chunk aligned to 256 bytes: the .text of JavaScriptCore's LowLevelInterpreter.cpp.obj (RVA 0x042b5600 in build 127915). It lies between Bun's own code and the CRT. A change to the code before it moves the CRT by a multiple of 256 bytes, or not at all. 127079 (#43600) and 127156, 127177 (#45637) branch from b28212a, two commits before #45593, and still link _powf_special at the same address.

The table. _powf_special comes from libucrt.lib(pow_special.obj). All 23 direct calls to it are in powf (the SSE2 path and the FMA3 path). In build 127915 (ed68082) it is at 0x1451ce490:

1451ce49f  cmp  r9d, 0x8
1451ce4a3  ja   0x1451ce5cd
1451ce4a9  lea  rdx, [rip - 0x51ce4b0]            # __ImageBase
1451ce4b0  mov  ecx, dword ptr [rdx + 4*r9 + 0x51ce5dc]
1451ce4b8  add  rcx, rdx
1451ce4bb  jmp  rcx
...
1451ce5d9  ret
1451ce5da  nop
1451ce5dc  9 RVAs: func+0x2d +0x57 +0x86 +0x86 +0x86 +0x98 +0xc4 +0x13d +0xf0
1451ce600  _realloc_base

An RVA is an address relative to the image base. The table starts at func+0x14c. Entry 6 is at func+0x164 and holds the RVA of func+0xc4.

The failing layout. The flagged address 0x14519c364 is entry 6, so the function was at 0x14519c200 and the entry held RVA 0x0519c2c4. The sweep through that table:

0x14519c34c  2d c2 19 05 57               sub
0x14519c351  c2 19 05                     ret
0x14519c354  86 c2                        xchg
0x14519c356  19 05 86 c2 19 05            sbb
0x14519c35c  86 c2                        xchg
0x14519c35e  19 05 98 c2 19 05            sbb
0x14519c364  c4 c2 19 05 3d c3 19 05 f0   vphsubw   <- flagged (AVX)
0x14519c36d  c2 19 05                     ret

I could not download the bun-windows-x64-profile.zip of build 126987 from my environment. The reproduction uses build 127915's artifact (the canary release asset) and the address from the CI log. The function is the same object in both: between the v1.4.3 release binary and build 127915, its code differs only in three relocated displacements, and the nine case offsets are equal.

Scanner runs (scripts/verify-baseline-static/CLAUDE.md steps, scanner built from this repository):

binary allowlist result
build 127915 with the 36 table bytes of the failing layout main FAIL: _powf_special [AVX] (1 insns), Vphsubw (AVX)
same this PR PASS, _powf_special is in the allowlisted group
v1.4.3 release with the same 36 bytes (file offset 0x42d99fc) main FAIL, the same violation
same this PR PASS
build 127915, not modified this PR PASS, _powf_special is a stale entry
v1.4.3 release, not modified this PR PASS, _powf_special is a stale entry

A stale entry is not an error. strcspn, strpbrk and strspn are stale in the same runs. In the CI runs of this PR (builds 128150 and 128539) the step passes with 0 violations.

How many functions have such a table. Two searches over .text, each run on build 127915 and on the v1.4.3 release, find the same four functions: strcspn, strspn and strpbrk with three tables each, and _powf_special with one.

  • By instruction: each mov r32, [base + index*4 + disp32] whose disp32 is an RVA inside the same function.
  • By content, with no disassembly: each run of four or more consecutive 4-byte words that are RVAs into the 64 KiB before the word.

The pinned libucrt.lib (10.0.26100.8249, scripts/build/winsysroot.ts) has 15 functions with such tables in 7 objects. The 11 that are not linked today are _pow_special, eight functions of filter_simd.obj, _XMMI_FP_Emulation and _XMMI2_FP_Emulation.

The PDB marks the tables. Each of the ten tables has an unnamed S_LDATA32 record with no type at its first byte, inside the function's S_GPROC32. llvm-pdbutil dump -symbols -modi=866 bun-profile.pdb shows _powf_special with code size 368 and the record at +0x14c. strcspn and strspn have records at +0x314, +0x350, +0x390, and strpbrk at +0x2fc, +0x338, +0x378. scan_aarch64 already skips data that the toolchain marks. scan_x86_64 takes no such ranges. A scan that skips these records makes the whole group unnecessary and checks the code of the four functions again. It must skip only 4-byte words that are RVAs into the function, not everything up to the function's end.

Layouts that flag each function. Each function was decoded with the scanner's own filters at every 16-byte-aligned RVA in 0x05000000..0x06000000 (1,048,576 positions):

function layouts flagged with a feature other than AVX
_powf_special 3,642 (0.35%) 2,810
strcspn 22,724 (2.17%) 10,242
strspn 22,724 (2.17%) 10,242
strpbrk 20,763 (1.98%) 10,313

The 0.35% is a mean over two regimes:

  • In the 64 KiB band RVA 0x05C50000..0x05C60000, 3,022 of 4,096 positions flag _powf_special (74%). Each entry then ends in C5 05, and C5 is a VEX prefix. With the function at RVA 0x05C51230 the table decodes as Vpmuludq and Vpunpckhqdq (AVX2), so an [AVX] ceiling fails there. strcspn, strspn and strpbrk each flag 4,072 of 4,096 positions in this band.
  • In the rest of the window, 620 of 1,044,480 positions flag it (0.06%). From the position in build 127915 up to the band, 468 of 692,224 do (0.07%).

The band starts 10.5 MiB above the position of _powf_special in build 127915.

Not in this change.

  • The scanner change that skips the tables. It changes what a merge gate skips, so it gets its own review.
  • llint_entry [AVX], the other data-in-.text group of this file. On Windows the interpreter is one symbol, so the decoder's restart at symbol starts does not help inside it.

Self-review. A review of this change raised 8 concerns. This push addresses 7: the build count, the cause, the rate and the scope in this description, and the PDB records in the description and in the group comment. The review also asked for a tracking issue for the scanner change. I did not file one.

Related. #40672 (open) lists the same tables in its notes. It does not add this entry.


no test proof · iteration 0 · build/CI scripts only; test-proof not applicable

…le on Windows x64

The Windows x64 static scan flags `_powf_special [AVX]` on some link
layouts. MSVC stores the 9 RVAs of the function's switch table in .text
after its `ret`, and the linear sweep decodes them as instructions. With
the function at RVA 0x0519c200 the table entry `C4 C2 19 05` and the five
bytes after it decode as VPHSUBW.

Add `_powf_special` as a blanket pass to the data-in-.text group of
allowlist-x64-windows.txt. The strspn family in that group has the same
kind of table.
@robobun

robobun commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator Author

Status

Ready for review and merge. The change is one allowlist entry and its comment.

CI on this commit

How I reproduced the failure

  1. Build the scanner: cargo build --release --manifest-path scripts/verify-baseline-static/Cargo.toml.
  2. Take bun-windows-x64-profile.zip of the bun-v1.4.3 release. In its bun-profile.exe the table of _powf_special is at file offset 0x42d99fc.
  3. Write the table bytes of the failing layout over those 36 bytes: 2d c2 19 05 57 c2 19 05 86 c2 19 05 86 c2 19 05 86 c2 19 05 98 c2 19 05 c4 c2 19 05 3d c3 19 05 f0 c2 19 05.
  4. Run the scanner on it with --allowlist scripts/verify-baseline-static/allowlist-x64-windows.txt.

With the allowlist of main, the scan fails with _powf_special [AVX] (1 insns) and Vphsubw (AVX), as in build 126987. With the allowlist of this branch, it passes. The same holds for the artifact of build 127915 (table at file offset 0x51cd9dc).

I could not download the artifact of build 126987 from my environment. The bytes in step 3 follow from the address in the CI log. The Notes block of the PR body shows how.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — a one-entry allowlist addition that follows the scanner's documented data-in-.text convention.

What was reviewed:

  • The flagged bytes C4 C2 19 05 do decode as a VEX3 0F38-map VPHSUBW (66-prefixed, opcode 05), consistent with a 4-byte RVA table entry rather than real code, and the 1-insn hit right after ret matches the triage guide's false-positive signature.
  • Bare (blanket) entry is the sanctioned exception in scripts/verify-baseline-static/CLAUDE.md for confirmed misdecodes; it does not interact with the gated powf [AVX, FMA] entry at line 957, which is a different symbol.
  • Group header count (4 symbols), ASCII sort order (_ before s), and comment placement match the existing strspn-family group; no scanner source or CI flags change.
Extended reasoning...

The change adds a single bare allowlist line plus an explanatory comment to scripts/verify-baseline-static/allowlist-x64-windows.txt, the CI-only static ISA scanner's Windows x64 suppression list; no runtime, build, or security-sensitive surface is touched. The byte sequence quoted in the PR decodes as claimed and the hit shape (one instruction, after the function's ret, inside a UCRT scalar-math helper) matches the repo's own triage guide for data-in-.text false positives, which explicitly prescribes a blanket pass. The only cost is that the scanner no longer bounds the 332-byte _powf_special body, the same trade-off already accepted for strspn/strcspn/strpbrk. The file is not covered by CODEOWNERS and the hunt ran dry with no findings.

@coderabbitai

coderabbitai Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: oven-sh/bun/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 27a6600c-da91-48f7-b481-e0d8a05f2839
📥 Commits

Reviewing files that changed from the base of the PR and between ed58ba2 and 410215e.

📒 Files selected for processing: 1
  • scripts/verify-baseline-static/allowlist-x64-windows.txt

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 1 remain after this review.

Walkthrough

The Windows x64 static-baseline allowlist now describes CRT inline switch tables as .text data false positives rather than CPU-feature gates. It adds _powf_special as an allowed symbol and retains strcspn, strpbrk, and strspn.

Changes

Windows x64 static baseline

Layer / File(s) Summary
Revise inline switch table allowlist
scripts/verify-baseline-static/allowlist-x64-windows.txt
The section now describes CRT inline switch tables as .text data false positives. It adds _powf_special and documents its SSE2-only code and in-function switch table. The three existing symbols remain listed.

Suggested reviewers: jarred-sumner

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to 41021

The entry leaves a bounded future-coverage gap for this symbol, but no current baseline-incompatible code is established and the repository permits blanket passes for confirmed .text data false positives. No current merge-blocking risk is demonstrated.

Pre-merge checks: Passed 4
Check name Status Explanation
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Title check Passed The title clearly identifies the main change: allowlisting the UCRT _powf_special switch table for Windows x64 baseline verification.
Description check Passed The description explains the problem, fix, verification steps, scope, tradeoffs, and related context. It does not use the template headings exactly, but it provides the required information and is sub…
Full details: Description check

Explanation

The description explains the problem, fix, verification steps, scope, tradeoffs, and related context. It does not use the template headings exactly, but it provides the required information and is substantially complete.

✨ Finishing Touches: 💡 1
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@robobun

robobun commented Oct 18, 2026

Copy link
Copy Markdown
Collaborator Author
Updated 1:05 AM PT - Oct 18th, 2026

@robobun, your commit 410215e is building: #128150

@robobun

robobun commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 5:55 PM PT - Oct 18th, 2026

✅ @robobun, your commit c299f4a0f293ab8fbcf968e0b08d98e66f660664 passed in Build #128539! 🎉


🧪   To try this PR locally:

bunx bun-pr 45886

That installs a local version of the PR into your bun-45886 executable, so you can run:

bun-45886 --bun

… tables

Each inline switch table of the four allowlisted CRT functions has an
unnamed S_LDATA32 record at its first byte, inside the function's
S_GPROC32. The group comment now says so, and that the scan does not read
those records.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review found no issues

No high-confidence issues detected in this change.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant